package vmcs.controller;

import java.util.Observable;
import java.util.Observer;

import vmcs.common.Constant;
import vmcs.common.VMCSException;
import vmcs.customer.ChangeGiver;
import vmcs.customer.CoinReceiver;
import vmcs.customer.DispenseController;
import vmcs.customer.state.ChangeGivenState;
import vmcs.customer.state.CoinInsertedState;
import vmcs.customer.state.DrinkDispensedState;
import vmcs.customer.state.DrinkSelectedState;
import vmcs.customer.state.EnoughCoinsInsertedState;
import vmcs.customer.state.IdleState;
import vmcs.customer.state.MachineTerminatedState;
import vmcs.customer.state.State;
import vmcs.ui.interfacecontrol.*;

public class TransactionController implements Observer{

	private ICustomerPanel customerPanel;
	private  MainController mainController;

	private DispenseController dispenseController;
	private CoinReceiver coinReceiver;
	private ChangeGiver changeGiver;

	private int selection;
	private int price;
	private int totalInsertedCoins;

	private State idleState; 
	private State drinkSelectedState;
	private State coinInsertedState; 
	private State enoughCoinsInserted; 
	private State drinkDispenseState;
	private State changeGivenState;
	private State machineTerminatedState;
	
	private State state;


	public TransactionController (MainController mainController){
		this.mainController = mainController;
		this.changeGiver = new ChangeGiver(this);
		this.coinReceiver = new CoinReceiver(this);
		this.dispenseController = new DispenseController(this);

		// State
		idleState = IdleState.getInstance(this);
		drinkSelectedState = DrinkSelectedState.getInstance(this);
		coinInsertedState = CoinInsertedState.getInstance(this);
		enoughCoinsInserted = EnoughCoinsInsertedState.getInstance(this); 
		drinkDispenseState = DrinkDispensedState.getInstance(this); 
		changeGivenState = ChangeGivenState.getInstance(this); 
		machineTerminatedState = MachineTerminatedState.getInstance(this);
		state = idleState;
		initialize();
	}

	public void initialize(){
		price = 0;
		selection = -1;
		totalInsertedCoins = 0;
	}


	public void startTransaction(int drinkSelectedIdx){
		state.selectDrink(drinkSelectedIdx);
	}

	public void insertCoin(int value) {
		state.insertCoin(value);
	}

	public void dispenseDrink() {
		state.dispenseDrink(selection);
	}

	public void giveChange() {
		state.giveChange(totalInsertedCoins-price);
	}

	public void  storeCash(){
		state.storeCash();
	}

	public void cancelTransaction(){
		state.cancel();
	}

	public void terminateMachine(){
		state.terminateMachine();
	}
	
	public void closeDown () {
		if (customerPanel == null)
			return;
		customerPanel.closeDown();
		ISimulatorPanel scp = mainController.getSimulatorControlPanel();
		scp.setPanelActive(Constant.ACT_CUSTOMER, true);
	}


	public void displayCustomerPanel(){
		ISimulatorPanel  simulationControlPanel = mainController.getSimulatorControlPanel();
		if(customerPanel == null)
			customerPanel = UIController.getCustomerPanel(simulationControlPanel, this);
		customerPanel.display();
		simulationControlPanel.setPanelActive(Constant.ACT_CUSTOMER, false);	        
	}




	public void setState(State state){
		this.state = state;
	}

	public State getIdleState() {
		return idleState;
	}

	public State getDrinkSelectedState() {
		return drinkSelectedState;
	}

	public State getCoinInsertedState() {
		return coinInsertedState;
	}

	public State getEnoughCoinsInserted() {
		return enoughCoinsInserted;
	}

	public State getDrinkDispenseState() {
		return drinkDispenseState;
	}

	public State getChangeGivenState() {
		return changeGivenState;
	}

	public State getMachineTerminatedState() {
		return machineTerminatedState;
	}
	
	public DispenseController getDispenseController() {
		return dispenseController;
	}

	public CoinReceiver getCoinReceiver() {
		return coinReceiver;
	}

	public ChangeGiver getChangeGiver() {
		return changeGiver;
	}

	public int getPrice() {
		return price;
	}

	public int getSelection() {
		return selection;
	}

	public State getState() {
		return state;
	}

	public ICustomerPanel getCustomerPanel() {
		return customerPanel;
	}

	public MainController getMainController() {
		return mainController;
	}

	/*
	public void terminateFault(Object Source) throws VMCSException{
		this.dispenseController.allowSelection(false);
		if(Source.getClass().getName().equalsIgnoreCase("DispenseController")){
			this.coinReceiver.refundCash();
		}
		if(Source.getClass().getName().equalsIgnoreCase("ChangeGiver")){
			this.coinReceiver.storeCash();
		}
		if(Source.getClass().getName().equalsIgnoreCase("CoinReceiver")){

		}
	}
*/

	public int getTotalInsertedCoins() {
		return totalInsertedCoins;
	}

	public void setTotalInsertedCoins(int totalInsertedCoins) {
		this.totalInsertedCoins = totalInsertedCoins;
	}

	public void setSelection(int selection) {
		this.selection = selection;
	}

	public void setPrice(int price) {
		this.price = price;
	}

	@Override
	public void update(Observable o, Object arg) {
		//current design does not require any update on the UI thus this is empty
		System.out.println("Update detected: " + this.toString());
		System.out.println("Object: "+arg.toString());
	}

}
